package com.example.teaching_server.service;

import com.example.teaching_server.dto.StudentDashboardDTO;
import com.example.teaching_server.entity.*;
import com.example.teaching_server.repository.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 学生仪表板服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class StudentDashboardService {

    private final UserRepository userRepository;
    private final ActivityRepository activityRepository;
    private final TeachingResourceRepository teachingResourceRepository;
    private final TeacherToolRepository teacherToolRepository;
    private final ClassRepository classRepository;
    private final NoticeRepository noticeRepository;
    private final NoticeTypeRepository noticeTypeRepository;

    /**
     * 获取学生仪表板数据
     */
    public StudentDashboardDTO getDashboardData(Long userId) {
        log.debug("获取学生仪表板数据: userId={}", userId);

        validateUserExists(userId);

        StudentDashboardDTO dto = new StudentDashboardDTO();
        dto.setClassName(getStudentClassName(userId));
        dto.setTools(getStudentTools());
        dto.setResources(getStudentResources(userId));
        dto.setClassActivities(getClassActivities(userId));
        dto.setCertificates(new ArrayList<>());
        return dto;
    }

    /**
     * 获取学生班级名称
     */
    private String getStudentClassName(Long userId) {
        try {
            UserEntity user = userRepository.findById(userId)
                    .orElseThrow(() -> new RuntimeException("用户不存在"));

            if (user.getClassId() != null) {
                ClassEntity classEntity = classRepository.findById(user.getClassId()).orElse(null);
                if (classEntity != null && classEntity.getClassName() != null) {
                    return classEntity.getClassName();
                }
            }
        } catch (Exception e) {
            log.warn("查询班级信息失败: userId={}, error={}", userId, e.getMessage());
        }
        return "未分配班级";
    }

    /**
     * 学生工具配置
     */
    private List<StudentDashboardDTO.ToolDTO> getStudentTools() {
        List<StudentDashboardDTO.ToolDTO> tools = new ArrayList<>();
        tools.add(createToolDTO("打卡", "Clock", true, "/student/activities"));
        tools.add(createToolDTO("通知", "BellFilled", true, "/student/notices"));
        tools.add(createToolDTO("请假", "DocumentDelete", false, "/student/leave-request"));
        tools.add(createToolDTO("问卷调查", "DocumentChecked", false, "/student/surveys"));
        tools.add(createToolDTO("上传成果", "Upload", false, "/student/achievements/upload"));
        tools.add(createToolDTO("课程资源", "Collection", true, "/student/resources"));
        return tools;
    }

    /**
     * 获取学生资源数据
     */
    private List<StudentDashboardDTO.ResourceDTO> getStudentResources(Long userId) {
        try {
            List<TeachingResource> teachingResources = teachingResourceRepository.findTop4ByOrderByCreatedAtDesc();
            List<StudentDashboardDTO.ResourceDTO> result = new ArrayList<>();

            for (int i = 0; i < teachingResources.size() && i < 4; i++) {
                TeachingResource resource = teachingResources.get(i);
                String category = getResourceCategory(i);
                result.add(convertTeachingResourceToDTO(resource, category));
            }
            return result;
        } catch (Exception e) {
            log.warn("获取资源数据失败: userId={}, error={}", userId, e.getMessage());
            return new ArrayList<>();
        }
    }


    /**
     * 获取班级活动数据
     */
    private List<StudentDashboardDTO.ClassActivityDTO> getClassActivities(Long userId) {
        try {
            List<StudentDashboardDTO.ClassActivityDTO> activities = new ArrayList<>();

            // 获取用户已报名的活动
            List<ActivityEntity> userActivities = activityRepository.findMyActivities(userId, 4);
            activities.addAll(convertActivitiesToDTOs(userActivities));

            // 获取真实的通知
            List<NoticeEntity> notices = getRandomNotices(2);
            activities.addAll(convertNoticesToDTOs(notices));

            // 按时间排序
            activities.sort((a1, a2) -> compareDates(a2.getUpdatedAt(), a1.getUpdatedAt()));
            return activities;
        } catch (Exception e) {
            log.warn("获取班级活动数据失败: userId={}, error={}", userId, e.getMessage());
            return new ArrayList<>();
        }
    }

    /**
     * 创建工具DTO
     */
    private StudentDashboardDTO.ToolDTO createToolDTO(String name, String icon, Boolean available, String route) {
        StudentDashboardDTO.ToolDTO tool = new StudentDashboardDTO.ToolDTO();
        tool.setName(name);
        tool.setIcon(icon);
        tool.setAvailable(available);
        tool.setRoute(route);
        return tool;
    }

    /**
     * 将教学活动转换为资源DTO
     */
    private StudentDashboardDTO.ResourceDTO convertTeachingResourceToDTO(TeachingResource resource, String category) {
        StudentDashboardDTO.ResourceDTO dto = new StudentDashboardDTO.ResourceDTO();
        dto.setId(resource.getId());
        dto.setTitle(resource.getTitle());
        dto.setType(getFileTypeFromUrl(resource.getFileUrl()));
        dto.setUpdatedAt(formatDate(resource.getUpdatedAt() != null ? resource.getUpdatedAt() : resource.getCreatedAt()));
        dto.setCategory(category);
        dto.setUrl("/student/resources/" + resource.getId());
        return dto;
    }

    /**
     * 获取资源分类
     */
    private String getResourceCategory(int index) {
        return index < 2 ? "class" : "subscription";
    }

    /**
     * 将活动列表转换为DTO列表
     */
    private List<StudentDashboardDTO.ClassActivityDTO> convertActivitiesToDTOs(List<ActivityEntity> activities) {
        return activities.stream()
                .map(activity -> {
                    String type = getActivityType(activity);
                    if ("notice".equals(type)) {
                        return convertNoticeToFullActivityDTO(activity, type);
                    } else {
                        return convertActivityToDTO(activity, type);
                    }
                })
                .collect(Collectors.toList());
    }

    /**
     * 将通知列表转换为DTO列表
     */
    private List<StudentDashboardDTO.ClassActivityDTO> convertNoticesToDTOs(List<NoticeEntity> notices) {
        return notices.stream()
                .map(notice -> convertNoticeToFullActivityDTO(notice, "notice"))
                .collect(Collectors.toList());
    }

    /**
     * 根据活动信息判断类型
     */
    private String getActivityType(ActivityEntity activity) {
        if (activity.getTitle() == null) {
            return "activity";
        }

        String title = activity.getTitle().toLowerCase();
        String description = activity.getDescription() != null ? activity.getDescription().toLowerCase() : "";

        if (title.contains("打卡") || description.contains("打卡")) {
            return "checkin";
        } else if (title.contains("实践") || description.contains("实践") ||
                title.contains("活动") || description.contains("活动")) {
            return "practice";
        } else if (title.contains("联系") || description.contains("联系") ||
                title.contains("家长") || description.contains("家长")) {
            return "contact";
        } else {
            return "activity";
        }
    }

    /**
     * 将活动实体转换为通知DTO
     */
    private StudentDashboardDTO.ClassActivityDTO convertNoticeToFullActivityDTO(ActivityEntity activity, String type) {
        StudentDashboardDTO.ClassActivityDTO dto = new StudentDashboardDTO.ClassActivityDTO();
        dto.setId(activity.getId());
        dto.setTitle(activity.getTitle());
        dto.setType(type);
        dto.setUpdatedAt(formatDateTime(activity.getStartDate() != null ?
                activity.getStartDate().atStartOfDay() : activity.getCreatedAt()));
        dto.setContent(activity.getDescription());
        dto.setDescription(activity.getDescription());
        dto.setNoticeTypeName("活动通知");
        dto.setSenderName("系统");
        dto.setCreateTime(formatDateTime(activity.getCreatedAt()));
        return dto;
    }

    /**
     * 将通知转换为完整活动DTO
     */
    private StudentDashboardDTO.ClassActivityDTO convertNoticeToFullActivityDTO(NoticeEntity notice, String type) {
        StudentDashboardDTO.ClassActivityDTO dto = new StudentDashboardDTO.ClassActivityDTO();
        dto.setId(notice.getNoticeId());
        dto.setTitle(notice.getTitle());
        dto.setType(type);
        dto.setUpdatedAt(formatDateTime(notice.getCreatedAt()));
        dto.setContent(notice.getContent());
        dto.setDescription(notice.getDescription());
        dto.setNoticeTypeName(getNoticeTypeName(Math.toIntExact(notice.getTypeId())));
        dto.setSenderName(getSenderName(notice.getCreatedBy()));
        dto.setCreateTime(formatDateTime(notice.getCreatedAt()));
        return dto;
    }

    /**
     * 将活动实体转换为DTO
     */
    private StudentDashboardDTO.ClassActivityDTO convertActivityToDTO(ActivityEntity activity, String type) {
        StudentDashboardDTO.ClassActivityDTO dto = new StudentDashboardDTO.ClassActivityDTO();
        dto.setId(activity.getId());
        dto.setTitle(activity.getTitle());
        dto.setType(type);
        dto.setUpdatedAt(formatDateTime(activity.getStartDate() != null ?
                activity.getStartDate().atStartOfDay() : activity.getCreatedAt()));
        return dto;
    }

    /**
     * 从通知表中随机获取几条通知
     */
    private List<NoticeEntity> getRandomNotices(int limit) {
        try {
            return noticeRepository.findTopNByOrderByCreatedAtDesc(limit);
        } catch (Exception e) {
            log.warn("获取通知失败: error={}", e.getMessage());
            return new ArrayList<>();
        }
    }

    /**
     * 获取通知类型名称
     */
    private String getNoticeTypeName(Integer typeId) {
        if (typeId == null) return "通知";

        try {
            Optional<NoticeTypeEntity> noticeType = noticeTypeRepository.findById(Long.valueOf(typeId));
            return noticeType.map(NoticeTypeEntity::getTypeName).orElse("通知");
        } catch (Exception e) {
            log.warn("获取通知类型失败: typeId={}", typeId);
            return "通知";
        }
    }

    /**
     * 获取发布人姓名
     */
    private String getSenderName(Long createdBy) {
        if (createdBy == null) return "系统管理员";

        try {
            Optional<UserEntity> sender = userRepository.findById(createdBy);
            return sender.map(UserEntity::getUsername).orElse("系统管理员");
        } catch (Exception e) {
            log.warn("获取发布人信息失败: createdBy={}", createdBy);
            return "系统管理员";
        }
    }

    /**
     * 日期比较方法
     */
    private int compareDates(String date1, String date2) {
        try {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
            LocalDateTime dt1 = LocalDateTime.parse(date1, formatter);
            LocalDateTime dt2 = LocalDateTime.parse(date2, formatter);
            return dt1.compareTo(dt2);
        } catch (Exception e) {
            log.warn("日期比较失败: date1={}, date2={}", date1, date2);
            return 0;
        }
    }

    /**
     * 根据文件URL获取文件类型
     */
    private String getFileTypeFromUrl(String fileUrl) {
        if (fileUrl == null) return "document";

        String lowerUrl = fileUrl.toLowerCase();
        if (lowerUrl.contains(".pdf")) return "pdf";
        if (lowerUrl.contains(".doc")) return "word";
        if (lowerUrl.contains(".mp4")) return "video";
        if (lowerUrl.contains(".jpg") || lowerUrl.contains(".png")) return "image";
        return "document";
    }

    /**
     * 格式化日期
     */
    private String formatDate(java.time.temporal.TemporalAccessor date) {
        if (date == null) return "";
        try {
            return DateTimeFormatter.ofPattern("yyyy-MM-dd").format(date);
        } catch (Exception e) {
            log.warn("日期格式化失败: date={}", date);
            return "";
        }
    }

    /**
     * 格式化日期时间
     */
    private String formatDateTime(java.time.temporal.TemporalAccessor dateTime) {
        if (dateTime == null) return "";
        try {
            return DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm").format(dateTime);
        } catch (Exception e) {
            log.warn("日期时间格式化失败: dateTime={}", dateTime);
            return "";
        }
    }

    /**
     * 验证用户是否存在
     */
    private void validateUserExists(Long userId) {
        if (!userRepository.existsById(userId)) {
            throw new RuntimeException("用户不存在: " + userId);
        }
    }
}
